# -*- coding:utf-8 -*-
## author : cypro666
## note   : python3.4+
"""
A simple logger used for background services
"""
import logging, os

__all__ = ['Logger']


class Logger(object):
    """ Usage:
        log = Logger('/var/project/yourname.log')
        log('some message')
        log('error happened!', 'error')
        ...
        `Logger.__call__` method supports 5 levels common used, they're:
        'DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL', lower case is also OK
    """
    def __init__(self, logfile):
        """ make sure logfile's path is existed and valid """
        assert(os.path.exists(os.path.dirname(logfile)))
        self._record = {
            'debug'     : logging.debug,
            'info'      : logging.info,
            'warn'      : logging.warn,
            'error'     : logging.error,
            'critical'  : logging.critical,
            'DEBUG'     : logging.debug,
            'INFO'      : logging.info,
            'WARN'      : logging.warn,
            'ERROR'     : logging.error,
            'CRITICAL'  : logging.critical
        }
        mode = 'w'
        level = logging.NOTSET
        datefmt = '%Y-%m-%d %H:%M:%S'
        msgformat = '%(asctime)s %(levelname)-8s %(message)s'
        logging.basicConfig(filename=logfile,
                            filemode=mode,
                            level=level,
                            datefmt=datefmt,
                            format=msgformat)
        self._logfile = logfile
        self._nlevel = {'DEBUG':0, 'INFO':0, 'WARN':0, 'ERROR':0, 'CRITICAL':0}
        self._nlines = 0

    def __del__(self):
        """ not nessesary """
        logging.shutdown()
    
    def check(self):
        """ check logfile exists or not """
        return os.path.exists(self._logfile);
    
    def filename(self):
        """ return real path of logfile """
        return os.path.realpath(self._logfile)
    
    def filesize(self):
        """ return size in byte of logfile """
        return os.path.getsize(self._logfile)
    
    def __call__(self, *messages, level = 'info'):
        """ logging messages to logfile under level given """ 
        assert(level in self._record)
        self._record[level](' '.join(map(lambda x : str(x), messages)));
        self._nlines += 1
        self._nlevel[level.upper()] += 1
    
    def record(self, dictargs):
        """ multi record """
        for msg, lv in dictargs.items():
            self._record[lv](msg); 
            self._nlines += 1
            self._nlevel[lv.upper()] += 1
    
    def current_lines(self):
        """ get number lines in current log file """ 
        return self._nlines
    
    def current_levels(self):
        """ get number levels in current log file """ 
        return self._nlevel.copy()


def test():
    """ test for Logger """
    log = Logger(os.path.expanduser('~') + os.sep + 'test.log')
    log.check()
    print('log file : %s' % log.filename())
    log('log test start...')
    log('this is warning!', level='warn')
    log('this is error!', level='error')
    log('this is debug: %s' % __name__, level='debug')
    log('some value:', 123456, level='info')
    log(1.2, 3.4, 666, 'xyz')
    log('more lines:\nsome line1\nsome line2\nsome line3', level='critical')
    log.record({'the first':'info', 'the second':'info'})
    log('log test finish...')
    print(log.current_lines())
    print(log.current_levels())
    print('log file size : %db' % log.filesize())
    
    
if __name__ == '__main__':
    test()

